package org.pp.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.pp.admin.dto.AuthUpate;
import org.pp.core.AdminConstants;
import org.pp.core.Assertion;
import org.pp.entity.SysMenu;
import org.pp.entity.SysRole;
import org.pp.entity.SysRoleMenu;
import org.pp.entity.SysUserRole;
import org.pp.mapper.SysRoleMapper;
import org.pp.service.ISysMenuService;
import org.pp.service.ISysRoleMenuService;
import org.pp.service.ISysRoleService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.pp.service.ISysUserRoleService;
import org.pp.util.RedisUtil;
import org.pp.vo.AdminMenuTreeVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * <p>
 * 系统角色 服务实现类
 * </p>
 *
 * @author haima
 * @since 2024-04-20
 */
@Service
public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> implements ISysRoleService {


    @Autowired
    RedisUtil redisUtil;

    @Autowired
    ISysRoleMenuService roleMenuService;

    @Autowired
    ISysUserRoleService userRoleService;

    @Autowired
    ISysMenuService menuService;

    @Override
    public void delete(String ids) {
        List<String> list = Arrays.asList(ids.split(","));
        if(CollectionUtil.isEmpty(list)){
            return;
        }
        removeBatchByIds(list);
        //角色和用户
        //角色和权限表
        for (String id : list) {
            redisUtil.delete(AdminConstants.roleAuths+":"+id);
        }
        //删除角色权限
        roleMenuService.remove(new LambdaQueryWrapper<SysRoleMenu>().in(SysRoleMenu::getRoleId,list));
        //删除用户角色
        userRoleService.remove(new LambdaQueryWrapper<SysUserRole>().in(SysUserRole::getRoleId,list));
    }


    @Override
    public List<Long> authGet(Long roleId) {
        List<SysRoleMenu> list = roleMenuService.list(new LambdaQueryWrapper<SysRoleMenu>().eq(SysRoleMenu::getRoleId, roleId));
        return list.stream().map(SysRoleMenu::getMenuId).toList();
    }

    @Override
    @Transactional
    public void authUpate(AuthUpate dto) {
        //方式1，重建，全部删除，重新插入
        //方式2，删除需要删除的，添加要增加
        Assertion.nullThrow(getById(dto.getRoleId()), "角色错误");
        dto.setMenuIds(menuService.listByIds(dto.getMenuIds()).stream().map(SysMenu::getMenuId).toList());
        Assertion.emptyThrow(dto.getMenuIds(), "权限id错误");

        List<SysRoleMenu> list = roleMenuService.list(new LambdaQueryWrapper<SysRoleMenu>()
                .eq(SysRoleMenu::getRoleId, dto.getRoleId())
                .notIn(SysRoleMenu::getMenuId, dto.getMenuIds())
        );
        List<Long> rmIds = list.stream().map(SysRoleMenu::getRoleMenueId).toList();
        if (!rmIds.isEmpty()) {
            roleMenuService.removeBatchByIds(rmIds);
        }
        //目前还有这些
        List<SysRoleMenu> remaindList = roleMenuService.list(new LambdaQueryWrapper<SysRoleMenu>()
                .eq(SysRoleMenu::getRoleId, dto.getRoleId())
        );

        //目前还存在的权限，需要新增的，过滤掉
        Set<Long> remaindIds = remaindList.stream().map(SysRoleMenu::getMenuId).collect(Collectors.toSet());
        List<Long> saveIds = dto.getMenuIds().stream().filter(e -> !remaindIds.contains(e)).toList();
        if (!saveIds.isEmpty()) {
            List<SysRoleMenu> roleMenus = saveIds.stream().map(e -> {
                SysRoleMenu roleMenu = new SysRoleMenu();
                roleMenu.setRoleId(dto.getRoleId());
                roleMenu.setMenuId(e);
                return roleMenu;
            }).toList();
            roleMenuService.saveBatch(roleMenus);
        }
        List<SysRoleMenu> current = dto.getMenuIds().stream().map(e -> {
            SysRoleMenu roleMenu = new SysRoleMenu();
            roleMenu.setRoleId(dto.getRoleId());
            roleMenu.setMenuId(e);
            return roleMenu;
        }).toList();
        refreshAuths(current);
    }

    @Override
    public void refreshAuths(List<SysRoleMenu> list) {
        Map<Long,List<Long>> mp= new ConcurrentHashMap<>();
        for (SysRoleMenu roleMenu : list) {
            if(!mp.containsKey(roleMenu.getRoleId())){
                mp.put(roleMenu.getRoleId(),new ArrayList<>());
            }
            mp.get(roleMenu.getRoleId()).add(roleMenu.getMenuId());
        }

        mp.forEach((k,v)->{
            List<AdminMenuTreeVo> tree = menuService.tree(v);
            List<String> auths = getAuths(tree);
            redisUtil.delete(AdminConstants.roleAuths+":"+k);
            if(!CollectionUtil.isEmpty(auths)){
                redisUtil.add(AdminConstants.roleAuths+":"+k,auths);
            }
        });
    }

    private List<String> getAuths(List<AdminMenuTreeVo> tree){
        List<String> res= new ArrayList<>();
        for (AdminMenuTreeVo vo : tree) {
            if(StrUtil.isNotBlank(vo.getApi())){
                res.add(vo.getApi());
            }
            if(!CollectionUtil.isEmpty(vo.getChildren())){
                res.addAll(getAuths(vo.getChildren()));
            }
        }
        return res;
    }
}
